home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / awt / Menu.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  15.1 KB  |  532 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)Menu.java    1.50 98/09/04
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package java.awt;
  15.  
  16. import java.util.Vector;
  17. import java.util.Enumeration;
  18. import java.awt.peer.MenuPeer;
  19. import java.awt.event.KeyEvent;
  20.  
  21. /**
  22.  * A <code>Menu</code> object is a pull-down menu component
  23.  * that is deployed from a menu bar.
  24.  * <p>
  25.  * A menu can optionally be a <i>tear-off</i> menu. A tear-off menu
  26.  * can be opened and dragged away from its parent menu bar or menu.
  27.  * It remains on the screen after the mouse button has been released.
  28.  * The mechanism for tearing off a menu is platform dependent, since
  29.  * the look and feel of the tear-off menu is determined by its peer.
  30.  * On platforms that do not support tear-off menus, the tear-off
  31.  * property is ignored.
  32.  * <p>
  33.  * Each item in a menu must belong to the <code>MenuItem</code>
  34.  * class. It can be an instance of <code>MenuItem</code>, a submenu
  35.  * (an instance of <code>Menu</code>), or a check box (an instance of
  36.  * <code>CheckboxMenuItem</code>).
  37.  *
  38.  * @version 1.50, 09/04/98
  39.  * @author Sami Shaio
  40.  * @see     java.awt.MenuItem
  41.  * @see     java.awt.CheckboxMenuItem
  42.  * @since   JDK1.0
  43.  */
  44. public class Menu extends MenuItem implements MenuContainer {
  45.  
  46.     static {
  47.         /* ensure that the necessary native libraries are loaded */
  48.     Toolkit.loadLibraries();
  49.         initIDs();
  50.     }
  51.  
  52.     /**
  53.      * A vector of the items that will be part of the Menu.
  54.      *
  55.      * @serial
  56.      * @see countItems()
  57.      */
  58.     Vector        items = new Vector();
  59.  
  60.     /**
  61.      * This field indicates whether the menu has the
  62.      * tear of property or not.  It will be set to
  63.      * <code>true</code> if the menu has the tear off
  64.      * property and it will be set to <code>false></code>
  65.      * if it does not.
  66.      * A torn off menu can be deleted by a user when
  67.      * it is no longer needed.
  68.      *
  69.      * @serial
  70.      * @see isTearOff()
  71.      */
  72.     boolean        tearOff;
  73.  
  74.     /**
  75.      * This field will be set to <code>true</code>
  76.      * if the Menu in question is actually a help
  77.      * menu.  Otherwise it will be set to <code>
  78.      * false</code>.
  79.      *
  80.      * @serial
  81.      */
  82.     boolean        isHelpMenu;
  83.  
  84.     private static final String base = "menu";
  85.     private static int nameCounter = 0;
  86.  
  87.     /*
  88.      * JDK 1.1 serialVersionUID
  89.      */
  90.      private static final long serialVersionUID = -8809584163345499784L;
  91.  
  92.     /**
  93.      * Constructs a new menu with an empty label. This menu is not
  94.      * a tear-off menu.
  95.      * @since      JDK1.1
  96.      */
  97.     public Menu() {
  98.     this("", false);
  99.     }
  100.  
  101.     /**
  102.      * Constructs a new menu with the specified label. This menu is not
  103.      * a tear-off menu.
  104.      * @param       label the menu's label in the menu bar, or in
  105.      *                   another menu of which this menu is a submenu.
  106.      */
  107.     public Menu(String label) {
  108.     this(label, false);
  109.     }
  110.  
  111.     /**
  112.      * Constructs a new menu with the specified label,
  113.      * indicating whether the menu can be torn off.
  114.      * <p>
  115.      * Tear-off functionality may not be supported by all
  116.      * implementations of AWT.  If a particular implementation doesn't
  117.      * support tear-off menus, this value is silently ignored.
  118.      * @param       label the menu's label in the menu bar, or in
  119.      *                   another menu of which this menu is a submenu.
  120.      * @param       tearOff   if <code>true</code>, the menu
  121.      *                   is a tear-off menu.
  122.      * @since       JDK1.0.
  123.      */
  124.     public Menu(String label, boolean tearOff) {
  125.     super(label);
  126.     this.tearOff = tearOff;
  127.     }
  128.  
  129.     /**
  130.      * Construct a name for this MenuComponent.  Called by getName() when
  131.      * the name is null.
  132.      */
  133.     String constructComponentName() {
  134.         synchronized (getClass()) {
  135.         return base + nameCounter++;
  136.     }
  137.     }
  138.  
  139.     /**
  140.      * Creates the menu's peer.  The peer allows us to modify the
  141.      * appearance of the menu without changing its functionality.
  142.      */
  143.     public void addNotify() {
  144.         synchronized (getTreeLock()) {
  145.         if (peer == null)
  146.             peer = Toolkit.getDefaultToolkit().createMenu(this);
  147.         int nitems = getItemCount();
  148.         for (int i = 0 ; i < nitems ; i++) {
  149.             MenuItem mi = getItem(i);
  150.         mi.parent = this;
  151.         mi.addNotify();
  152.         }
  153.     }
  154.     }
  155.  
  156.     /**
  157.      * Removes the menu's peer.  The peer allows us to modify the appearance
  158.      * of the menu without changing its functionality.
  159.      */
  160.     public void removeNotify() {
  161.         synchronized (getTreeLock()) {
  162.         int nitems = getItemCount();
  163.         for (int i = 0 ; i < nitems ; i++) {
  164.             getItem(i).removeNotify();
  165.         }
  166.         super.removeNotify();
  167.     }
  168.     }
  169.  
  170.     /**
  171.      * Indicates whether this menu is a tear-off menu.
  172.      * <p>
  173.      * Tear-off functionality may not be supported by all
  174.      * implementations of AWT.  If a particular implementation doesn't
  175.      * support tear-off menus, this value is silently ignored.
  176.      * @return      <code>true</code> if this is a tear-off menu;
  177.      *                         <code>false</code> otherwise.
  178.      */
  179.     public boolean isTearOff() {
  180.     return tearOff;
  181.     }
  182.  
  183.     /**
  184.       * Get the number of items in this menu.
  185.       * @return     the number of items in this menu.
  186.       * @since      JDK1.1
  187.       */
  188.     public int getItemCount() {
  189.     return countItems();
  190.     }
  191.  
  192.     /**
  193.      * @deprecated As of JDK version 1.1,
  194.      * replaced by <code>getItemCount()</code>.
  195.      */
  196.     public int countItems() {
  197.     return countItemsImpl();
  198.     }
  199.  
  200.     /*
  201.      * This is called by the native code, so client code can't
  202.      * be called on the toolkit thread.
  203.      */
  204.     final int countItemsImpl() {
  205.     return items.size();
  206.     }
  207.  
  208.     /**
  209.      * Gets the item located at the specified index of this menu.
  210.      * @param     index the position of the item to be returned.
  211.      * @return    the item located at the specified index.
  212.      */
  213.     public MenuItem getItem(int index) {
  214.     return getItemImpl(index);
  215.     }
  216.  
  217.     /*
  218.      * This is called by the native code, so client code can't
  219.      * be called on the toolkit thread.
  220.      */
  221.     final MenuItem getItemImpl(int index) {
  222.     return (MenuItem)items.elementAt(index);
  223.     }
  224.  
  225.     /**
  226.      * Adds the specified menu item to this menu. If the
  227.      * menu item has been part of another menu, remove it
  228.      * from that menu.
  229.      * @param       mi   the menu item to be added.
  230.      * @return      the menu item added.
  231.      * @see         java.awt.Menu#insert(java.lang.String, int)
  232.      * @see         java.awt.Menu#insert(java.awt.MenuItem, int)
  233.      */
  234.     public MenuItem add(MenuItem mi) {
  235.         synchronized (getTreeLock()) {
  236.         if (mi.parent != null) {
  237.             mi.parent.remove(mi);
  238.         }
  239.         items.addElement(mi);
  240.         mi.parent = this;
  241.         MenuPeer peer = (MenuPeer)this.peer;
  242.         if (peer != null) {
  243.             mi.addNotify();
  244.         peer.addItem(mi);
  245.         }
  246.         return mi;
  247.     }
  248.     }
  249.  
  250.     /**
  251.      * Adds an item with the specified label to this menu.
  252.      * @param       label   the text on the item.
  253.      * @see         java.awt.Menu#insert(java.lang.String, int)
  254.      * @see         java.awt.Menu#insert(java.awt.MenuItem, int)
  255.      */
  256.     public void add(String label) {
  257.     add(new MenuItem(label));
  258.     }
  259.  
  260.     /**
  261.      * Inserts a menu item into this menu
  262.      * at the specified position.
  263.      * @param         menuitem  the menu item to be inserted.
  264.      * @param         index     the position at which the menu
  265.      *                          item should be inserted.
  266.      * @see           java.awt.Menu#add(java.lang.String)
  267.      * @see           java.awt.Menu#add(java.awt.MenuItem)
  268.      * @exception     IllegalArgumentException if the value of
  269.      *                    <code>index</code> is less than zero.
  270.      * @since         JDK1.1
  271.      */
  272.  
  273.     public void insert(MenuItem menuitem, int index) {
  274.         synchronized (getTreeLock()) {
  275.         if (index < 0) {
  276.             throw new IllegalArgumentException("index less than zero.");
  277.         }
  278.  
  279.         int nitems = getItemCount();
  280.         Vector tempItems = new Vector();
  281.  
  282.         /* Remove the item at index, nitems-index times 
  283.            storing them in a temporary vector in the
  284.            order they appear on the menu.
  285.         */
  286.         for (int i = index ; i < nitems; i++) {
  287.             tempItems.addElement(getItem(index));
  288.         remove(index);
  289.         }
  290.  
  291.         add(menuitem);
  292.  
  293.         /* Add the removed items back to the menu, they are
  294.            already in the correct order in the temp vector.
  295.         */
  296.         for (int i = 0; i < tempItems.size()  ; i++) {
  297.             add((MenuItem)tempItems.elementAt(i));
  298.         }
  299.     }
  300.     }
  301.  
  302.     /**
  303.      * Inserts a menu item with the specified label into this menu
  304.      * at the specified position.
  305.      * @param       label the text on the item.
  306.      * @param       index the position at which the menu item
  307.      *                      should be inserted.
  308.      * @see         java.awt.Menu#add(java.lang.String)
  309.      * @see         java.awt.Menu#add(java.awt.MenuItem)
  310.      * @since       JDK1.1
  311.      */
  312.  
  313.     public void insert(String label, int index) {
  314.         insert(new MenuItem(label), index);
  315.     }
  316.  
  317.     /**
  318.      * Adds a separator line, or a hypen, to the menu at the current position.
  319.      * @see         java.awt.Menu#insertSeparator(int)
  320.      */
  321.     public void addSeparator() {
  322.     add("-");
  323.     }
  324.  
  325.     /**
  326.      * Inserts a separator at the specified position.
  327.      * @param       index the position at which the
  328.      *                       menu separator should be inserted.
  329.      * @exception   IllegalArgumentException if the value of
  330.      *                       <code>index</code> is less than 0.
  331.      * @see         java.awt.Menu#addSeparator
  332.      * @since       JDK1.1
  333.      */
  334.  
  335.     public void insertSeparator(int index) {
  336.         synchronized (getTreeLock()) {
  337.         if (index < 0) {
  338.             throw new IllegalArgumentException("index less than zero.");
  339.         }
  340.  
  341.         int nitems = getItemCount();
  342.         Vector tempItems = new Vector();
  343.  
  344.         /* Remove the item at index, nitems-index times 
  345.            storing them in a temporary vector in the
  346.            order they appear on the menu.
  347.         */
  348.         for (int i = index ; i < nitems; i++) {
  349.             tempItems.addElement(getItem(index));
  350.         remove(index);
  351.         }
  352.  
  353.         addSeparator();
  354.  
  355.         /* Add the removed items back to the menu, they are
  356.            already in the correct order in the temp vector.
  357.         */
  358.         for (int i = 0; i < tempItems.size()  ; i++) {
  359.             add((MenuItem)tempItems.elementAt(i));
  360.         }
  361.     }
  362.     }
  363.  
  364.     /**
  365.      * Removes the menu item at the specified index from this menu.
  366.      * @param       index the position of the item to be removed.
  367.      */
  368.     public void remove(int index) {
  369.         synchronized (getTreeLock()) {
  370.         MenuItem mi = getItem(index);
  371.         items.removeElementAt(index);
  372.         MenuPeer peer = (MenuPeer)this.peer;
  373.         if (peer != null) {
  374.             mi.removeNotify();
  375.         mi.parent = null;
  376.         peer.delItem(index);
  377.         }
  378.     }
  379.     }
  380.  
  381.     /**
  382.      * Removes the specified menu item from this menu.
  383.      * @param       item the item to be removed from the menu
  384.      */
  385.     public void remove(MenuComponent item) {
  386.         synchronized (getTreeLock()) {
  387.         int index = items.indexOf(item);
  388.         if (index >= 0) {
  389.             remove(index);
  390.         }
  391.     }
  392.     }
  393.  
  394.     /**
  395.      * Removes all items from this menu.
  396.      * @since       JDK1.0.
  397.      */
  398.     public void removeAll() {
  399.         synchronized (getTreeLock()) {
  400.         int nitems = getItemCount();
  401.         for (int i = 0 ; i < nitems ; i++) {
  402.             remove(0);
  403.         }
  404.     }
  405.     }
  406.  
  407.     /*
  408.      * Post an ActionEvent to the target of the MenuPeer
  409.      * associated with the specified keyboard event (on
  410.      * keydown).  Returns true if there is an associated
  411.      * keyboard event.
  412.      */
  413.     boolean handleShortcut(KeyEvent e) {
  414.         int nitems = getItemCount();
  415.         for (int i = 0 ; i < nitems ; i++) {
  416.             MenuItem mi = getItem(i);
  417.             if (mi.handleShortcut(e)) {
  418.                 return true;
  419.             }
  420.         }
  421.         return false;
  422.     }
  423.  
  424.     MenuItem getShortcutMenuItem(MenuShortcut s) {
  425.     int nitems = getItemCount();
  426.     for (int i = 0 ; i < nitems ; i++) {
  427.             MenuItem mi = getItem(i).getShortcutMenuItem(s);
  428.             if (mi != null) {
  429.                 return mi;
  430.             }
  431.     }
  432.         return null;
  433.     }
  434.  
  435.     synchronized Enumeration shortcuts() {
  436.         Vector shortcuts = new Vector();
  437.         int nitems = getItemCount();
  438.     for (int i = 0 ; i < nitems ; i++) {
  439.             MenuItem mi = getItem(i);
  440.             if (mi instanceof Menu) {
  441.                 Enumeration e = ((Menu)mi).shortcuts();
  442.                 while (e.hasMoreElements()) {
  443.                     shortcuts.addElement(e.nextElement());
  444.                 }
  445.             } else {
  446.                 MenuShortcut ms = mi.getShortcut();
  447.                 if (ms != null) {
  448.                     shortcuts.addElement(ms);
  449.                 }
  450.             }
  451.     }
  452.         return shortcuts.elements();
  453.     }
  454.  
  455.     void deleteShortcut(MenuShortcut s) {
  456.     int nitems = getItemCount();
  457.     for (int i = 0 ; i < nitems ; i++) {
  458.         getItem(i).deleteShortcut();
  459.     }
  460.     }
  461.  
  462.  
  463.     /* Serialization support.  A MenuContainer is responsible for
  464.      * restoring the parent fields of its children.
  465.      */
  466.  
  467.     /**
  468.      * The menu serialized Data Version.
  469.      *
  470.      * @serial
  471.      */
  472.     private int menuSerializedDataVersion = 1;
  473.  
  474.     /**
  475.      * Writes default serializable fields to stream.  Writes
  476.      * a list of serializable ItemListener(s) as optional data.
  477.      * The non-serializable ItemListner(s) are detected and
  478.      * no attempt is made to serialize them.
  479.      *
  480.      * @serialData Null terminated sequence of 0 or more pairs.
  481.      *             The pair consists of a String and Object.
  482.      *             The String indicates the type of object and
  483.      *             is one of the following :
  484.      *             itemListenerK indicating and ItemListener object.
  485.      *
  486.      * @see AWTEventMulticaster.save(ObjectOutputStream, String, EventListener)
  487.      * @see java.awt.Component.itemListenerK
  488.      */
  489.     private void writeObject(java.io.ObjectOutputStream s)
  490.       throws java.lang.ClassNotFoundException,
  491.          java.io.IOException
  492.     {
  493.       s.defaultWriteObject();
  494.     }
  495.  
  496.     /**
  497.      * Read the ObjectInputStream and if it isnt null
  498.      * add a listener to receive item events fired
  499.      * by the Menu.
  500.      * Unrecognised keys or values will be Ignored.
  501.      *
  502.      * @see removeActionListener()
  503.      * @see addActionListener()
  504.      */
  505.     private void readObject(java.io.ObjectInputStream s)
  506.       throws java.lang.ClassNotFoundException,
  507.          java.io.IOException
  508.     {
  509.       s.defaultReadObject();
  510.       for(int i = 0; i < items.size(); i++) {
  511.     MenuItem item = (MenuItem)items.elementAt(i);
  512.     item.parent = this;
  513.       }
  514.     }
  515.  
  516.     /**
  517.      * Gets the parameter string representing the state of this menu.
  518.      * This string is useful for debugging.
  519.      * @since      JDK1.0nu.
  520.      */
  521.     public String paramString() {
  522.         String str = ",tearOff=" + tearOff+",isHelpMenu=" + isHelpMenu;
  523.         return super.paramString() + str;
  524.     }
  525.  
  526.     /**
  527.      * Initialize JNI field and method IDs
  528.      */
  529.     private static native void initIDs();
  530. }
  531.  
  532.